package cn.miju.unionpay.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.miju.common.content.CodeMessage;
import cn.miju.common.util.OkHttpUtil;
import cn.miju.common.util.ValidationUtil;
import cn.miju.unionpay.constant.UnionPayConstant;
import cn.miju.unionpay.model.ReversalRequest;
import cn.miju.unionpay.model.ReversalResponse;
import cn.miju.unionpay.model.UnionPayRequest;
import cn.miju.unionpay.model.UnionPayResponse;
import cn.miju.unionpay.properties.UnionPayProperties;
import cn.miju.unionpay.request.UnionPayCloseOrderReq;
import cn.miju.unionpay.response.UnionPayBaseResp;
import cn.miju.unionpay.util.UnionPaySignUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;

/**
 * <pre>
 * 关闭订单（仅支付被扫码关单，不支持主扫码）
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-16 21:25
 */
@Slf4j
@Component
public class UnionPayCloseOrderHandler extends AbstractUnionPayHandler<UnionPayCloseOrderReq, UnionPayBaseResp> {
    /**
     * 可选返回参数(如果接口所需参数不满足需求，可按照官方接口文档，原样传入对应参数)
     */
    private Set<String> optionalRespParams;
    @Override
    public ReversalRequest beforeRequest(UnionPayCloseOrderReq req) {
        ValidationUtil.validate(req);
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        UnionPayRequest request = super.beforeRequest(req);
        request.setTxnType(UnionPayConstant.TxnType.REVERSAL);
        request.setTxnSubType(UnionPayConstant.TxnSubType.REVERSAL);
        request.setBizType(UnionPayConstant.BizType.DEFAULT);
        request.setChannelType(UnionPayConstant.ChannelType.MOBILE);
        request.setMerId(unionPayProperties.getMerchantNo());
        ReversalRequest reversalRequest = BeanUtil.copyProperties(request, ReversalRequest.class);
        reversalRequest.setOrderId(req.getOutTradeNo());
        optionalRespParams = req.getOptionalRespParams();
        super.setOptionalReqParams(reversalRequest, req.getOptionalReqParams());
        return reversalRequest;
    }

    /**
     * 核心执行
     *
     * @param req {@link UnionPayCloseOrderReq}
     * @return {@link UnionPayBaseResp}
     */
    @Override
    public UnionPayBaseResp doPlan(UnionPayCloseOrderReq req) {
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        ReversalRequest request = this.beforeRequest(req);
        // 签名
        Map<String, String> param = JSONObject.parseObject(JSONObject.toJSONString(request), Map.class);
        UnionPaySignUtil.sign(param, unionPayProperties.getSignCertPath(), unionPayProperties.getSignCertPwd());
        String reqParam = UnionPaySignUtil.createLinkString(param, false, true, StandardCharsets.UTF_8.toString());
        // 请求
        log.info("API--冲正--> Request：{}", reqParam);
        String result = OkHttpUtil.doPost(unionPayProperties.getServiceUrl(), reqParam);
        log.info("API--冲正--> Response：{}", result);
        if (StringUtils.isBlank(result)) {
            return UnionPayBaseResp.builder().code(CodeMessage.FAIL.getCode()).msg("响应数据为空").build();
        }
        ReversalResponse response = JSONObject.parseObject(JSONObject.toJSONString(UnionPaySignUtil.readLinkStr(result)), ReversalResponse.class);
        return this.afterResponse(response);
    }

    /**
     * 响应参数后置处理
     *
     * @param resp 响应参数
     * @return 结果
     */
    @Override
    public UnionPayBaseResp afterResponse(UnionPayResponse resp) {
        UnionPayBaseResp baseResp = UnionPayBaseResp.preBuilder(CodeMessage.FAIL);
        ReversalResponse response = (ReversalResponse) resp;
        baseResp.setMsg(StringUtils.isEmpty(response.getRespMsg()) ? baseResp.getMsg() : response.getRespMsg());
        if (response.isSuccess()) {
            baseResp = UnionPayBaseResp.preBuilder(CodeMessage.SUCCESS);
            baseResp.setOptionalRespParams(super.getOptionalRespParams(response, optionalRespParams));
        }
        if ("34".equals(response.getRespCode())) {
            baseResp = UnionPayBaseResp.preBuilder(CodeMessage.TRADE_NOT_EXIT);
        }
        if ("43".equals(response.getRespCode())) {
            baseResp = UnionPayBaseResp.preBuilder(CodeMessage.TRADE_NOT_AUTH);
        }
        return baseResp;
    }
}
